#include "Parser.h"
#include "Compilation.h"
#include <exception>
#include <cstdlib>
#include <iostream>

#ifdef _WIN32
#include <windows.h>
#include <tchar.h> 
#include <strsafe.h>
#endif


using namespace std;
string testDirectory = "C:\\Temp\\a5";
string stdlibDirectory = "C:\\Users\\Michael\\Google Drive\\Repositories\\mlgamble-workspace\\CS444\\tests\\stdlibs\\5.0";
//string stdlibDirectory = "D:\\Google Drive\\Repositories\\mlgamble-workspace\\CS444\\tests\\stdlibs\\4.0";
const char *escapedCharacterDFA = "C:\\Temp\\EscapedCharacter.dfa";

#ifdef _WIN32

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

void runTest(vector<string> files, bool result){
	//cout << "**" << endl;
	//cout << "Expected result: " << result << endl;
	//for (unsigned int i = 0; i < files.size(); i++){
	//	cout << files[i] << endl;
	//}

	/*cout << endl;*/
	Compilation c;

	bool parse_failed = false;
	bool type_resolution_failed = false;

	for (vector<string>::iterator it = files.begin(); it < files.end(); ++it) {
		Parser p("C:\\Temp\\JOOS.pt", it->c_str(), "C:\\Temp\\Scanner.dfa");
		if (!p.IsAValidProgram()) { parse_failed = true; break; }
		c.Add((CompilationUnitNode*)p.Root());
	}

	//PrintVisitor pv = PrintVisitor(/*ofstream("C:\\Temp\\astout.txt")*/);
	//c.Accept(&pv);

	if (!parse_failed) c.Compile();
	else type_resolution_failed = true;
	wofstream stream("C:\\Temp\\astout.txt");
	PrintVisitor pv = PrintVisitor(&stream);
	c.Accept(&pv);
	type_resolution_failed = c.error != Compilation::None;
	if (result != ( !parse_failed && !type_resolution_failed)) {
		cout << " X ";
		//for (unsigned int i = 0; i < files.size(); i++) {
		//	cout << files[i] << endl;
		//	cout << endl;
		//}
	}
	cout << endl;
	
}


void recursiveGetFiles(vector<string> *files, string directory)
{

	//cout << "recursive get called on " << directory << endl;

	WIN32_FIND_DATA ffd;
	TCHAR szDir[MAX_PATH];
	HANDLE hFind = INVALID_HANDLE_VALUE;

	string searchPath = directory;
	searchPath.append("\\*");

	StringCchCopy(szDir, MAX_PATH, searchPath.c_str());

	hFind = FindFirstFile(szDir, &ffd);

	do
	{

		string fileName = ffd.cFileName;

		if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{

			if (fileName != "." && fileName != ".."){

				recursiveGetFiles(files, directory + "\\" + ffd.cFileName);

			}
		}
		else if (fileName.substr(fileName.size() - 5) == ".java")
		{
			//single file, save it for testing
			(*files).push_back(directory + "\\" + fileName);

		}
	} while (FindNextFile(hFind, &ffd) != 0);

}

int main(int argc, char *argv[]) {

	vector<string> stdlib_files;	
	recursiveGetFiles(&stdlib_files, "C:\\Temp\\Custom");
	//stdlib_files.push_back("C:\\Temp\\a4\\J1_7_Reachability_WhileTrue_ConstantFolding.java");
	//stdlib_files.push_back("C:\\Temp\\Custom\\Main.java");
	recursiveGetFiles(&stdlib_files, stdlibDirectory);
	
	runTest(stdlib_files, true);return 0;

	//this is the windows code for gathering files for tests in visual studio

	WIN32_FIND_DATA ffd;
	TCHAR szDir[MAX_PATH];
	HANDLE hFind = INVALID_HANDLE_VALUE;
	

	string searchPath = testDirectory;
	searchPath.append("\\*");

	StringCchCopy(szDir, MAX_PATH, searchPath.c_str());

	hFind = FindFirstFile(szDir, &ffd);

	if (INVALID_HANDLE_VALUE == hFind)
	{
		cout << "File handle fail" << endl;
	}

	do
	{

		vector<string> filesToTest = stdlib_files;

		string fileName = ffd.cFileName;

		bool expectedValue;

		if (fileName[1] == 'e'){
			expectedValue = 0;
		}

		else {
			expectedValue = 1;
		}

		if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{

			if (fileName != "." && fileName != ".."){

				cout << "** Directory: " << ffd.cFileName;
				recursiveGetFiles(&filesToTest, testDirectory + "\\" + ffd.cFileName);
				runTest(filesToTest, expectedValue);

			}
		}
		else
		{
			//single file, test it
			cout << "** File: " << ffd.cFileName;
			filesToTest.push_back(testDirectory + "\\" + fileName);
			runTest(filesToTest, expectedValue);	

		}
	} while (FindNextFile(hFind, &ffd) != 0);




	getchar(); //prevents windows console from closing down
	return 0;
	
}


#elif defined __unix__

int main(int argc, char *argv[]) {



	//this is final release code for gathering files from command line

	vector<string> inputFiles;

	if (argc < 2){
		cerr << "no input files, exiting" << endl;
	}

	else {
		for (int i = 1; i < argc; i++)
		{
			inputFiles.push_back(argv[i]);
		}
	}

	//Run the code on input files


	/*
	bool b;
	Parser p("D:\\CS444\\JOOS.pt", "D:\\CS444\\A.java", "D:\\CS444\\Scanner.dfa");
	b = p.IsAValidProgram();
	cout << b << endl;

	ClassVisitor classGetter;
	p.AbstractSyntaxTree()._root->Accept(classGetter);
	p.AbstractSyntaxTree().Print();

	*/
}

#endif